#ifndef TX_GRPC_H
#define TX_GRPC_H
#include <functional>
#include <string>
#include <future>
#include <memory>

#ifdef TX_GRPC_EXPORTS
#define TX_GRPC_API __declspec(dllexport)    
#else
#define TX_GRPC_API __declspec(dllimport)
#endif

#ifdef WIN32
class TX_GRPC_API TxGrpc
#else
class __attribute__((visibility("default"))) TxGrpc
#endif
{
public:
    //收到客户端数据后，处理后通过SENDER给客户端发送应答数据
    using SENDER = std::function<void(const std::string &)>;

    //客户端收到服务端数据的回调
    using CLIENT_RECV_DATA_CALLBACK = std::function<void(const std::string& data)>;
    
    /*服务端收到客户端以流式发送数据时的回调，通过此回调把数据给应用层处理
    *@param: string &data, 客户端发送来的数据
    *@std::string &peer, 客户端ip和端口，格式 ip:port
    *SENDER sender， 通过sender把应答数据发送给客户端
    */
    using SERVER_RECV_DATA_CALLBACK = std::function<void(const std::string &data, const std::string &peer, SENDER sender)>;
    
    using sptr = std::shared_ptr<TxGrpc>;

    TxGrpc() = default;

    virtual ~TxGrpc() = default;

    static sptr create();

    /*
    * 启动服务
    * @param uint16_t listenPort 监听的端口
    * @param uint16_t threadCount 非流式服务线程数，默认为1， 当为0时表示不启用非流式服务
    * @param uint16_t streamThreadCount 流式服务线程数，默认为1， 当为0时表示不启用流式服务
    */
    virtual bool StartServer(uint16_t listenPort, uint16_t threadCount = 1, uint16_t streamThreadCount = 1) = 0;

    /*
    * 停止服务
    */
    virtual void StopServer() = 0;

    /*
    * 与服务端建立连接
    */
    virtual bool Connect(const char *ip, uint16_t port) = 0;

    /*
    * 与服务端断开连接
    */
    virtual void DisConnect() = 0;

    //客户端非流式发送（同步发送）
    virtual std::string SendData(const char *data, uint16_t dataLen) = 0;

    //客户端非流式发送（异步发送）
    virtual bool AsyncSendMData(const char *data, uint16_t dataLen) = 0;

    //客户端流式发送（异步）
    virtual bool SendStreamData(const char *data, uint16_t dataLen) = 0;

    //设置客户端接收到服务端数据时的回调函数
    virtual void SetClientRecvDataCallback(CLIENT_RECV_DATA_CALLBACK callback) = 0;

    //设置服务端接收到客户端发送的数据时的回调函数
    virtual void SetServerRecvDataCallback(SERVER_RECV_DATA_CALLBACK callback) = 0;

    /*设置SSL证书
    *当不需要加密传输时可不调用此函数
    * @param const char *serverCrtFile 服务端crt文件
    * @param const char *serverKeyFile 服务端key文件
    * @param const char *clientCrtFile 客户端crt文件
    * @param const char *clientKeyFile 客户端key文件
    * @param const char *domain 生成证书时/CN=后面填的值
    */
    virtual void SetSSLKey(const char *serverCrtFile, const char *serverKeyFile
                         , const char *clientCrtFile, const char *clientKeyFile
                         , const char *domain) = 0;

};

#endif